/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE").
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR
 * COPYRIGHT LAW IS PROHIBITED.
 *
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE
 * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 *
 */
package l1j.server.server.clientpackets;

import java.util.logging.Logger;

import l1j.server.Config;
import l1j.server.echo.ClientThread;

public abstract class ClientBasePacket {
	private static Logger _log = Logger.getLogger(ClientBasePacket.class.getName());

	private static final String CLIENT_LANGUAGE_CODE = Config.CLIENT_LANGUAGE_CODE;

	private byte _decrypt[];

	private int _off;

	/**
	 * 返回客戶端的封包類型。("[C] C_DropItem" 等)
	 */
	public String getType() {
		return "[C] " + this.getClass().getSimpleName();
	}

	/**
	 * 結束byte[]取回
	 */
	public void over() {
		try{
			this._decrypt = null;
			this._off = 0;

		} catch (final Exception e) {
			_log.warning(e.getLocalizedMessage());
		}
	}

	/**
	 * 載入BYTE陣列
	 *
	 * @param abyte0
	 */
	protected void read(final byte abyte0[]) {
		try{
			this._decrypt = abyte0;
			this._off = 1;// 忽略第一個封包(OP編組)

		} catch (final Exception e) {
			_log.warning(e.getLocalizedMessage());
		}
	}

	/**
	 * 由byte[]中取回一組byte[]
	 *
	 * @return
	 */
	protected byte[] readByte() {
		final byte[] result = new byte[this._decrypt.length - this._off];
		try {
			System.arraycopy(this._decrypt, this._off, result, 0, this._decrypt.length - this._off);
			this._off = this._decrypt.length;

		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return result;
	}

	/**
	 * 由byte[]中取回一個byte
	 *
	 * @return
	 */
	protected int readC() {
		try{
			if (this._decrypt == null) {
				return 0x00;
			}
			if (this._decrypt.length < this._off + 1) {
				return 0x00;
			}
			final int i = this._decrypt[this._off++] & 0xff;

			return i;
		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return 0x00;
	}

	/**
	 * 由byte[]中取回一個short
	 *
	 * @return
	 */
	protected int readCH() {
		try{
			if (this._decrypt == null) {
				return 0x00;
			}
			if (this._decrypt.length < this._off + 3) {
				return 0x00;
			}
			int i = this._decrypt[this._off++] & 0xff;
			i |= this._decrypt[this._off++] << 8 & 0xff00;
			i |= this._decrypt[this._off++] << 16 & 0xff0000;

			return i;

		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return 0x00;
	}

	/*
	public int readD() {
		int i = _decrypt[_off++] & 0xff;
		i |= _decrypt[_off++] << 8 & 0xff00;
		i |= _decrypt[_off++] << 16 & 0xff0000;
		i |= _decrypt[_off++] << 24 & 0xff000000;
		return i;
	}

	public int readC() {
		int i = _decrypt[_off++] & 0xff;
		return i;
	}

	public int readH() {
		int i = _decrypt[_off++] & 0xff;
		i |= _decrypt[_off++] << 8 & 0xff00;
		return i;
	}

	public int readCH() {
		int i = _decrypt[_off++] & 0xff;
		i |= _decrypt[_off++] << 8 & 0xff00;
		i |= _decrypt[_off++] << 16 & 0xff0000;
		return i;
	}

	public double readF() {
		long l = _decrypt[_off++] & 0xff;
		l |= _decrypt[_off++] << 8 & 0xff00;
		l |= _decrypt[_off++] << 16 & 0xff0000;
		l |= _decrypt[_off++] << 24 & 0xff000000;
		l |= (long) _decrypt[_off++] << 32 & 0xff00000000L;
		l |= (long) _decrypt[_off++] << 40 & 0xff0000000000L;
		l |= (long) _decrypt[_off++] << 48 & 0xff000000000000L;
		l |= (long) _decrypt[_off++] << 56 & 0xff00000000000000L;
		return Double.longBitsToDouble(l);
	}

	public String readS() {
		String s = null;
		try {
			s = new String(_decrypt, _off, _decrypt.length - _off, CLIENT_LANGUAGE_CODE);
			s = s.substring(0, s.indexOf('\0'));
			_off += s.getBytes(CLIENT_LANGUAGE_CODE).length + 1;
		} catch (Exception e) {
			_log.log(Level.SEVERE, "OpCode=" + (_decrypt[0] & 0xff), e);
		}
		return s;
	}

	public byte[] readByte() {
		byte[] result = new byte[_decrypt.length - _off];
		try {
			System.arraycopy(_decrypt, _off, result, 0, _decrypt.length - _off);
			_off = _decrypt.length;
		} catch (Exception e) {
			_log.log(Level.SEVERE, "OpCode=" + (_decrypt[0] & 0xff), e);
		}
		return result;
	}
/**
	 * 由byte[]中取回一個int
	 *
	 * @return
	 */
	protected int readD() {
		try{
			//10: 01010
			//20: 10100
			//X=: 11110(30)
			//00010
			//10000
			if (this._decrypt == null) {
				return 0x00;
			}
			if (this._decrypt.length < this._off + 4) {
				return 0x00;
			}

			int i = this._decrypt[this._off++] & 0xff;
			i |= this._decrypt[this._off++] << 8 & 0xff00;
			i |= this._decrypt[this._off++] << 16 & 0xff0000;
			i |= this._decrypt[this._off++] << 24 & 0xff000000;

			return i;
		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return 0x00;
	}

	/**
	 * 由byte[]中取回一個double
	 *
	 * @return
	 */
	protected double readF() {
		try{
			if (this._decrypt == null) {
				return 0x00;
			}
			if (this._decrypt.length < this._off + 8) {
				return 0D;
			}
			long l = this._decrypt[this._off++] & 0xff;
			l |= this._decrypt[this._off++] << 8 & 0xff00;
			l |= this._decrypt[this._off++] << 16 & 0xff0000;
			l |= this._decrypt[this._off++] << 24 & 0xff000000;
			l |= (long) this._decrypt[this._off++] << 32 & 0xff00000000L;
			l |= (long) this._decrypt[this._off++] << 40 & 0xff0000000000L;
			l |= (long) this._decrypt[this._off++] << 48 & 0xff000000000000L;
			l |= (long) this._decrypt[this._off++] << 56 & 0xff00000000000000L;

			return Double.longBitsToDouble(l);

		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return 0D;
	}

	/**
	 * 由byte[]中取回一個short
	 *
	 * @return
	 */
	protected int readH() {
		try{
			if (this._decrypt == null) {
				return 0x00;
			}
			if (this._decrypt.length < this._off + 2) {
				return 0x00;
			}
			int i = this._decrypt[this._off++] & 0xff;
			i |= this._decrypt[this._off++] << 8 & 0xff00;

			return i;

		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return 0x00;
	}

	/**
	 * 由byte[]中取回一個String
	 *
	 * @return
	 */
	protected String readS() {
		String s = null;
		try {
			if (this._decrypt == null) {
				return s;
			}
			s = new String(this._decrypt, this._off, this._decrypt.length - this._off,CLIENT_LANGUAGE_CODE);
			s = s.substring(0, s.indexOf('\0'));
			this._off += s.getBytes(CLIENT_LANGUAGE_CODE).length + 1;

		} catch (final Exception e) {
			//_log.error("OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);
		}
		/*} catch (final NullPointerException e) {// 要求的byte內容為空
			ClientError.isPackError(_log, "OpCode:" + (_decrypt[0] & 0xff) + "/" + _decrypt.length, e);

		} catch (final ArrayIndexOutOfBoundsException e) {// 非法長度
			// 要求的byte索引位置超過byte.length
			_log.error("索引位置錯誤:" + _off + "/" + _decrypt.length, e);

		} catch (final Exception e) {
			_log.error(e.getLocalizedMessage(), e);
		}*/
		return s;
	}
	/**
	 * 執行客戶端封包處理接口
	 */
	public abstract void start(byte[] decrypt, ClientThread client) throws Exception;
}
